import { delay } from 'redux-saga';
import { call, race, put, select } from 'redux-saga/effects';
import { get, forEach, map } from 'lodash';
import axios from 'axios';
import urljoin from 'url-join';

import {
  toggleErrorInfo,
  toggleLoading,
  toggleLoginFailureDialog,
} from '../actions';
import { getStore } from '../store';

const encodeURLBody = params => {
  if (!params) {
    return '';
  }
  const keys = Object.keys(params);
  const encodedParams = map(keys, key => `${key}=${params[key]}`).join('&');
  return encodedParams;
};

function processErrMsg(err) {
  // 当响应异常时做一些处理
  if (err && err.response) {
    switch (err.response.status) {
      case 400:
        err.message = '请求错误(400)';
        break;
      case 401:
        err.message = '未授权，请重新登录(401)';
        break;
      case 403:
        err.message = '拒绝访问(403)';
        break;
      case 404:
        err.message = '请求出错(404)';
        break;
      case 408:
        err.message = '请求超时(408)';
        break;
      case 500:
        err.message = '服务器错误(500)';
        break;
      case 501:
        err.message = '服务未实现(501)';
        break;
      case 502:
        err.message = '网络错误(502)';
        break;
      case 503:
        err.message = '服务不可用(503)';
        break;
      case 504:
        err.message = '网络超时(504)';
        break;
      case 505:
        err.message = 'HTTP版本不受支持(505)';
        break;
      default:
        err.message = `连接出错(${err.response.status})!`;
    }
  } else {
    err.message = '连接服务器失败!';
  }
}

function* fetchServerDataSaga({ payload }) {
  const {
    path,
    method,
    callback,
    errCallback,
    header,
    body,
    showError = true,
    showLoading = true,
    successTip,
  } = payload;
  const state = getStore().getState();
  console.log('111---1111', state);
  const apiServer = get(state, ['common', 'apiServer']);
  console.log('222---2222', apiServer);
  const deviceId = get(state, ['common', 'deviceId'], '');
  const ticket = get(state, ['common', 'ticket'], '');
  console.log(
    `=======> network apiServer:${apiServer}, deviceId:${deviceId}, ticket:${ticket}`
  );
  let url = urljoin([apiServer, path]);

  showLoading && (yield put(toggleLoading({ visible: true })));

  let requestHeader = { imei: deviceId };
  if (!path.match(/\/a\//)) {
    // 需要登录的接口，header要加ticket
    requestHeader = { ...requestHeader, ticket: ticket };
  }

  if (header) {
    const keys = Object.getOwnPropertyNames(header);
    forEach(keys, key => {
      let val = header[key];
      if (val instanceof Object) {
        val = JSON.stringify(val);
      }
      requestHeader[key] = val;
    });
  }
  console.log('====> header:', requestHeader);

  let errorMsg = '';
  let errorCode = -1;

  let requestBody = null;
  if (body) {
    if (method && method === 'get') {
      const params = `?${encodeURLBody(body)}`;
      url = url.concat(params);
    } else {
      requestBody = JSON.stringify(body);
    }
  }

  const config = {
    method: method || 'post',
    url,
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      ...requestHeader,
    },
    data: requestBody,
  };

  let result;
  try {
    result = yield race({
      io: call(axios, config),
      timeout: call(delay, 60 * 1000), // 后台处理较慢，将超时时间延长到60s
    });
  } catch (e) {
    // 校正一些错误码
    processErrMsg(e);
    errorMsg = e.message;
    errorCode = -1;

    showLoading && (yield put(toggleLoading({ visible: false })));
    showError &&
      (yield put(toggleErrorInfo({ visible: true, text: errorMsg })));
    const error = {
      code: errorCode,
      message: errorMsg,
    };
    errCallback && errCallback(error);
    return;
  }

  if (result.timeout) {
    errorMsg = '请求超时';
    errorCode = -1;

    showLoading && (yield put(toggleLoading({ visible: false })));
    showError &&
      (yield put(toggleErrorInfo({ visible: true, text: errorMsg })));
    const error = {
      code: errorCode,
      message: errorMsg,
    };
    errCallback && errCallback(error);
    return;
  }

  const responseBody = get(result, ['io', 'data']);
  try {
    console.log('====> response', responseBody);

    const errorCode = get(responseBody, 'code', -1);

    if (errorCode === 0) {
      // 成功
      const data = get(responseBody, 'data', {});
      showLoading &&
        (yield put(toggleLoading({ visible: false, successTip: successTip })));
      callback && callback(data);
    } else {
      if (!path.match(/\/getTicket/) && (errorCode === 1 || errorCode === 30)) {
        // ticket失效 或 资金账号登录已失效,且不是 getTicket 接口, getTicket有单独的处理
        showLoading && (yield put(toggleLoading({ visible: false })));
        yield put(toggleLoginFailureDialog({ visible: true }));
      } else {
        // 请求失败
        const errorMsg = get(responseBody, 'message', '请求失败');
        showLoading && (yield put(toggleLoading({ visible: false })));
        showError &&
          (yield put(toggleErrorInfo({ visible: true, text: errorMsg })));

        const error = {
          code: errorCode,
          message: errorMsg,
        };
        errCallback && errCallback(error);
      }
    }
  } catch (e) {
    console.log('=====> network error:', e);
    errorMsg = '未知错误';
    errorCode = -1;

    const error = {
      code: errorCode,
      message: errorMsg,
    };
    showLoading && (yield put(toggleLoading({ visible: false })));
    showError &&
      (yield put(toggleErrorInfo({ visible: true, text: errorMsg })));

    errCallback && errCallback(error);
  }
}

export { fetchServerDataSaga };
